package com.nuumoblie.bluetoothtools.bt

import android.Manifest
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.bluetooth.BluetoothDevice
import android.content.pm.PackageManager
import android.os.Handler
import android.text.TextUtils
import android.util.Log
import android.view.View
import android.widget.*
import androidx.core.app.ActivityCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.jakewharton.rxbinding2.view.RxView
import com.nuumobile.filepicker.controller.DialogSelectionListener
import com.nuumoblie.bluetoothtools.BaseActivity
import com.nuumoblie.bluetoothtools.R
import es.dmoral.toasty.Toasty
import io.reactivex.functions.Consumer
import kotlinx.android.synthetic.main.activity_bt_client.*
import kotlinx.android.synthetic.main.activity_bt_client.tv_log
import kotlinx.android.synthetic.main.activity_bt_client.tv_tips
import kotlinx.android.synthetic.main.activity_bt_server.*
import java.io.File
import java.util.*


class BtClientActivity : BaseActivity(), BtManager.Callback, DevicesListAdapter.Listener,
    View.OnClickListener {


    val mBtManager: BtManager by lazy { BtManager(this, this) };
    var mRecyclerView: RecyclerView? = null;
    var mAdapter: DevicesListAdapter? = null;
    var mDevicesLists: DevicesLists? = null;

    var mEtInputFilePath: EditText? = null;
    var mEtInputMsg: EditText? = null;
    var mBtnSelectFile: Button? = null;
    var mBtnSendFile: Button? = null;
    var mBtnSendMsg: Button? = null;
    var mCbVerify: CheckBox? = null;
    var mCbMatch: CheckBox? = null;

    var mCycleIndexs: Int = 0;
    var mCurrentIndex: Int = 0;
    var mReConnectTime: Int = 0;
    var isReconnect: Boolean = false;
    var isWorking: Boolean = false;
    var mCurrentDevice: BluetoothDevice? = null;
    var mTvInfo: TextView? = null;
    var mTvSpeed: TextView? = null;

    var mBtnSetting: Button? = null;
    var mBtnExpanded: Button? = null;

    var mHandler: Handler = Handler();

    var isMatch: Boolean = false;

    override fun getContentLayoutId(): Int {
        return R.layout.activity_bt_client;
    }

    override fun initView() {
        mRecyclerView = findViewById(R.id.rv_devices);
        mEtInputFilePath = findViewById(R.id.input_file)
        mEtInputMsg = findViewById(R.id.input_msg)
        mBtnSelectFile = findViewById(R.id.btn_file_select);
        mCbVerify = findViewById(R.id.cb_verify)
        mBtnSendFile = findViewById(R.id.btn_file)
        mBtnSendMsg = findViewById(R.id.btn_msg)
        mTvInfo = findViewById(R.id.tv_info)
        mTvSpeed = findViewById(R.id.tv_speed)
        mBtnSetting = findViewById(R.id.btn_setting)
        mBtnExpanded = findViewById(R.id.btn_expanded)
        mCbMatch = findViewById(R.id.cb_bonded);

        if (ActivityCompat.checkSelfPermission(
                this,
                Manifest.permission.BLUETOOTH_SCAN
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.BLUETOOTH_SCAN), 12)
        }

    }

    override fun initData() {
        mRecyclerView?.layoutManager = LinearLayoutManager(this);
        mAdapter = DevicesListAdapter(this);
        mRecyclerView?.adapter = mAdapter;
        mDevicesLists = DevicesLists();
    }

    override fun initEvent() {
        RxView.clicks(btn_stop)
            .subscribe({ v ->
                mBtManager.cancelDiscovery();
            });
        RxView.clicks(btn_scan)
            .compose(rxPermissions.ensure(android.Manifest.permission.ACCESS_COARSE_LOCATION))
            .subscribe(Consumer<Boolean> { granted ->
                if (granted) {
                    mBtManager.scan();
                } else {
                    Toasty.warning(this@BtClientActivity, "权限", Toast.LENGTH_SHORT).show();
                }
            })

        mBtnSendMsg?.setOnClickListener(this)
        mBtnSendFile?.setOnClickListener(this)
        mBtnSelectFile?.setOnClickListener(this)
        mBtnSetting?.setOnClickListener(this)
        mBtnExpanded?.setOnClickListener(this)
        mCbMatch?.setOnCheckedChangeListener { buttonView, isChecked ->
            isMatch = isChecked;
        }
    }

    override fun onClick(v: View?) {
        when (v?.id) {
            R.id.btn_file_select -> {
                selectFile(DialogSelectionListener {
                    mEtInputFilePath?.setText(it[0]);
                })
            }
            R.id.btn_file -> {
                sendFile();
                mCurrentIndex = 0;
                isWorking = true;
                isReconnect = cb_re_isconnect.isChecked;
                var timestr = et_cycle_times.text.toString();
                if (TextUtils.isEmpty(timestr)) {
                    mCycleIndexs = 0;
                } else {
                    mCycleIndexs = timestr.toInt();
                }
            }
            R.id.btn_msg -> sendMsg();
            R.id.btn_setting -> {
                showOrHideSetting()
            };
            R.id.btn_expanded -> {
                ll_list.visibility = if (ll_list.isShown) View.GONE else View.VISIBLE
            }
        }
    }

    fun showOrHideSetting() {
        ll_setting_layout.visibility = if (ll_setting_layout.isShown) View.GONE else View.VISIBLE


//        var settingAnim = ValueAnimator.ofFloat(
//            if (ll_setting_layout.scaleY==0f) 0f else 1f,
//            if (ll_setting_layout.scaleY==0f) 1f else 0f
//        );
//        settingAnim.duration = 1000;
//        settingAnim.addUpdateListener(ValueAnimator.AnimatorUpdateListener { animation ->
//            ll_setting_layout.pivotY = 0f;
//            ll_setting_layout.scaleY = animation.animatedValue as Float
//        })
//        settingAnim.addListener(object : AnimatorListenerAdapter() {
//            override fun onAnimationEnd(animation: Animator?) {
//                super.onAnimationEnd(animation)
//
//            }
//
//            override fun onAnimationStart(animation: Animator?) {
//                super.onAnimationStart(animation)
//                ll_setting_layout.visibility = View.VISIBLE;
//            }
//        })
//        settingAnim.start()
    }


    fun sendMsg() {
        if (mBtManager.isConnected(null)) {
            val msg = mEtInputMsg?.getText().toString()
            if (TextUtils.isEmpty(msg))
                Toasty.warning(this, "消息不能空", 0).show();
            else
                mBtManager.sendMsg(msg)
        } else
            Toasty.warning(this, "没有连接", 0).show()
    }

    fun sendFile() {
        if (mBtManager.isConnected(null)) {
            val filePath = mEtInputFilePath?.getText().toString()
            if (TextUtils.isEmpty(filePath) || !File(filePath).isFile())
                Toasty.warning(this, "文件无效", 0).show()
            else {
                val file = File(filePath)
                if (file.length() == 0L) {
                    Toasty.warning(this, "文件无效", 0).show()
                    return;
                }
                mBtManager.sendFile(filePath, mCbVerify?.isChecked ?: false);
                enableOrDisableView(false)
            }
        } else
            Toasty.warning(this, "没有连接", 0).show();
    }


    override fun scanStart() {
        btn_scan.isEnabled = false;
        btn_stop.isEnabled = true;
        mDevicesLists?.clear();
    }

    override fun foundDevice(device: BluetoothDevice?) {
        mDevicesLists?.addDevices(device);
        mAdapter?.setDevices(mDevicesLists?.allDevices);
    }

    override fun discoveryFinish() {
        btn_scan.isEnabled = true;
        btn_stop.isEnabled = false;
    }

    fun disconnect(view: View) {
        mBtManager.disconnect(mCurrentDevice)
    }

    override fun onItemClick(dev: BluetoothDevice?) {
        if (mBtManager.isConnected(dev)) {
            Toasty.warning(this, "已经连接了", 0).show();
            return
        }
        if (isMatch) {
            if (dev?.bondState == BluetoothDevice.BOND_NONE) {
                var bond = dev?.createBond();
                Log.v("lmjssjj", "" + bond)
                tv_tips.setText("请配对...")
                return;
            } else if (dev?.bondState == BluetoothDevice.BOND_BONDING) {
                tv_tips.setText("正在配对请稍后...")
                return;
            }
        }
        mBtManager.connect(dev, isMatch)
        Toasty.warning(this, "正在连接(match:" + isMatch + ")...", 0).show();
        tv_tips.setText("正在连接...")

    }

    override fun socketNotify(state: Int, obj: Any?) {
        if (isDestroyed)
            return
        var msg: String? = null
        when (state) {
            BtOptBase.Listener.CONNECTED -> {
                val dev = obj as BluetoothDevice
                mCurrentDevice = dev;
                msg = String.format("与%s(%s)连接成功", dev.name, dev.address)
                tv_tips.setText(msg)
                if (isWorking && mCycleIndexs > 0 && mCurrentIndex < mCycleIndexs) {
                    sendFile();
                }
                mCbMatch?.isEnabled = false;
            }
            BtOptBase.Listener.DISCONNECTED -> {
                msg = "连接断开"
                tv_tips.setText(msg)
                if (cb_re_isconnect.isChecked) {
                    mHandler.postDelayed(Runnable {
                        if (!mBtManager.isConnected(mCurrentDevice)) {
                            mBtManager.connect(mCurrentDevice, isMatch)
                            tv_tips.setText("正在连接...")
                            mReConnectTime++;
                        }
                    }, 1000);
                } else {
                    enableOrDisableView(true)
                    mCbMatch?.isEnabled = true;
                }
            }
            BtOptBase.Listener.MSG -> {
                msg = String.format("\n%s", obj)
                tv_log.append(msg)
                dealWithMsg(msg)
            }
            BtOptBase.Listener.SPEED -> {
                msg = String.format("%s", obj)
                mTvSpeed?.setText(msg);
            }
        }
//        if (state != BtOptBase.Listener.SPEED)
//            Toasty.warning(this, msg ?: "", 0).show();
        showInfo()
    }


    fun dealWithMsg(msg: String) {
        if (msg.contains("文件发送完成")) {
            optViewEnable();
            Log.v("lmjssjj", "--------------");
        }
        showInfo()
    }

    fun optViewEnable() {
        if (mCycleIndexs == 0) {
            enableOrDisableView(true)
        } else if (mCurrentIndex < mCycleIndexs) {
            mHandler.postDelayed({
                mCurrentIndex++;
                sendFile();
            }, 3000);

        } else {
            enableOrDisableView(true)
        }
    }

    fun enableOrDisableView(enable: Boolean) {
        if (enable) {
            mBtnSendFile?.isEnabled = true;
            mBtnSendMsg?.isEnabled = true;
            mEtInputFilePath?.isEnabled = true;
            mEtInputMsg?.isEnabled = true;
            et_cycle_times.isEnabled = true
            cb_re_isconnect.isEnabled = true
            mBtnSelectFile?.isEnabled = true;
            isWorking = false;
        } else {
            mBtnSelectFile?.isEnabled = false
            mBtnSendFile?.isEnabled = false;
            mBtnSendMsg?.isEnabled = false;
            mEtInputFilePath?.isEnabled = false;
            mEtInputMsg?.isEnabled = false;
            et_cycle_times.isEnabled = false
            cb_re_isconnect.isEnabled = false
            isWorking = true;
        }
    }

    fun clearLog(view: View) {
        tv_log.setText("LOG\n")
    }

    fun showInfo() {
        mTvInfo?.setText("" + isReconnect + " : " + mReConnectTime + " -- " + mCycleIndexs + " : " + mCurrentIndex);
    }

    override fun onDestroy() {
        super.onDestroy()
        mBtManager.cancelDiscovery();
        mBtManager.unRegister();
    }


}